/*
 *  Filename:lsv_volume_storage_file_impl.c
 *  Description:
 *
 *  Created on: 2017年3月2日
 *  Author: Asdf(825674301)
 */
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#include "lsv.h"
#include "list.h"
#include "lsv_conf.h"
#include "lsv_help.h"
#include "lsv_volume_file_impl.h"

static inline int _lsv_storfile_name_get(char *storfile_name,
		lsv_u32_t storfile_id) 
		{
	sprintf(storfile_name, LSV_VOLUME_STORAGE_FILE_PREFIX"%u", storfile_id);
	return 0;
}
static inline int _lsv_storfile_info_free(
		lsv_volume_storage_file_info_t *storfile_info) {
	if (storfile_info) {
		free(storfile_info);
	}
	return 0;
}

int lsv_volume_storage_create(lsv_volume_proto_t *lsv_volume_proto) {
	int rc = 0;
	uint32_t storfile_id;
	char storfile_name[strlen(LSV_VOLUME_STORAGE_FILE_PREFIX) + 11];
	lsv_s32_t storfile_fd;
	lsv_volume_storage_file_info_t *storfile_info = NULL;

	storfile_id = lsv_volume_proto->ino;
	_lsv_storfile_name_get(storfile_name, storfile_id);

	storfile_fd = open(storfile_name, O_RDWR | O_CREAT | O_TRUNC, 0660);
	DINFO("create %s,storfile_fd:%d\n", storfile_name, storfile_fd);
	if (storfile_fd == -1) {
		rc = -EIO;
		DERROR("open file err,errno:%d\n", rc);
		goto ERR;
	}
	storfile_info = (lsv_volume_storage_file_info_t*) malloc(
			sizeof(lsv_volume_storage_file_info_t));
	if (NULL == storfile_info) {
		rc = ENOMEM;
		DERROR("malloc failed,errno:%d\n", rc);
		goto ERR;
	}
	storfile_info->storfile_id = storfile_id;
	storfile_info->storfile_fd = storfile_fd;
	lsv_volume_proto->storage_info = storfile_info;

	return 0;
	ERR: _lsv_storfile_info_free(storfile_info);
	return rc;
}

int lsv_volume_storage_open(lsv_volume_proto_t *lsv_volume_proto) {
	int rc = 0;
	lsv_u32_t storfile_id;
	char storfile_name[strlen(LSV_VOLUME_STORAGE_FILE_PREFIX) + 11];
	lsv_s32_t storfile_fd;
	lsv_volume_storage_file_info_t *storfile_info = NULL;

	storfile_id = lsv_volume_proto->ino;
	_lsv_storfile_name_get(storfile_name, storfile_id);

	storfile_fd = open(storfile_name, O_RDWR, 0660);
	DINFO("open %s storfile_fd:%d\n", storfile_name, storfile_fd);
	if (storfile_fd == -1) {
		rc = -EIO;
		DERROR("open file err,errno:%d\n", rc);
		goto ERR;
	}
	storfile_info = (lsv_volume_storage_file_info_t*) malloc(
			sizeof(lsv_volume_storage_file_info_t));
	if (NULL == storfile_info) {
		rc = ENOMEM;
		DERROR("malloc failed,errno:%d\n", rc);
		goto ERR;
	}
	storfile_info->storfile_id = storfile_id;
	storfile_info->storfile_fd = storfile_fd;
	lsv_volume_proto->storage_info = storfile_info;

	return 0;
	ERR: _lsv_storfile_info_free(storfile_info);
	return rc;
}

int lsv_volume_storage_write(lsv_volume_proto_t *lsv_volume_proto,
		int8_t *buf, lsv_u8_t type, lsv_u64_t offset, lsv_u32_t size) {
#if DRW
	DINFO("write_data offset:%llu,size:%llu\n", (LLU)offset, (LLU)size);
#endif
	return pwrite(
			((lsv_volume_storage_file_info_t*) (lsv_volume_proto->storage_info))->storfile_fd,
			buf, size, offset);
}

int lsv_volume_storage_read(lsv_volume_proto_t *lsv_volume_proto,
		lsv_u64_t offset, lsv_u32_t size, int8_t *buf) {
	int rc = 0;

#if DRW
	DINFO("read_date offset:%llu,size:%llu\n", (LLU)offset, (LLU)size);
#endif

	rc =
			pread(
					((lsv_volume_storage_file_info_t*) (lsv_volume_proto->storage_info))->storfile_fd,
					buf, size, offset);
	if (rc < 0) {
		DBUG("read_date err.rc:%d,errno:%d\n", rc, errno);
	}
	return 0;
}

int lsv_volume_storage_close(lsv_volume_proto_t *lsv_volume_proto) {
	int rc = 0;
	lsv_s32_t storfile_fd;
	lsv_volume_storage_file_info_t *storfile_info = NULL;

	storfile_info =
			(lsv_volume_storage_file_info_t *) lsv_volume_proto->storage_info;
	storfile_fd = storfile_info->storfile_fd;

	DINFO("close storage file fd:%d\n", storfile_fd);
	rc = close(storfile_fd);
	if (rc == -1) {
		DERROR("close file err,errno:%d\n", rc);
	}

	_lsv_storfile_info_free(storfile_info);
	lsv_volume_proto->storage_info = NULL;
	return rc;
}

int lsv_volume_storage_delete(lsv_volume_proto_t *lsv_volume_proto) {
	int rc = 0;
	lsv_u32_t storfile_id;
	char storfile_name[strlen(LSV_VOLUME_STORAGE_FILE_PREFIX) + 11];
	lsv_s32_t storfile_fd;
	lsv_volume_storage_file_info_t *storfile_info = NULL;

	storfile_info =
			(lsv_volume_storage_file_info_t *) lsv_volume_proto->storage_info;
	storfile_fd = storfile_info->storfile_fd;
	storfile_id = storfile_info->storfile_id;
	_lsv_storfile_name_get(storfile_name, storfile_id);

	DINFO("delete storage file %s fd:%d\n", storfile_name, storfile_fd);
	rc = close(storfile_fd);
	if (rc == -1) {
		DERROR("close file err,errno:%d\n", rc);
	}
	rc = remove(storfile_name);
	if (rc == -1) {
		DERROR("remove file err,errno:%d\n", rc);
	}

	_lsv_storfile_info_free(storfile_info);
	lsv_volume_proto->storage_info = NULL;
	return rc;
}

lsv_volume_storage_operations file_op = {
	.create = lsv_volume_storage_create,
	.delete = lsv_volume_storage_delete,
	.open = lsv_volume_storage_open,
	.close = lsv_volume_storage_close,
	.write = lsv_volume_storage_write,
	.read = lsv_volume_storage_read,
};
